<?php
class Sandbox {
	public $mem_limit = 4096;
	public $time_limit = 1.0;
	public $file_limit = 1;
	public $syscall_limit = 1;
	
	public $allow_file_path = array();
	
	public $stdin;
	public $stdout;
	public $stderr;
	
	public $command;
	public $sandbox;
	
	public $meta_content;
	public $out_content;
	
	public $time,$walltime,$mem;
	public $status;
	public $meta;
	
	public function __construct($cmd = '', $sandbox = '') {
		$this->command = $cmd;
		if (empty($sandbox)) {
			$this->sandbox = TEMP_BIN . '/sandbox';
		}
		chmod($this->sandbox, 0777);
	}
	
	public function execute() {
		$filepath = implode(' -p ', $this->allow_file_path);
		if (!empty($filepath))
			$filepath = ' -p ' . $filepath;
		$cmd = sprintf('%s -i %s -o %s -r %s -m %d -k %d -a %d -f %s -t %s -vvv -M - -- %s',
			$this->sandbox, // %s
			$this->stdin, // -i %s
			$this->stdout, // -o %s
			$this->stderr, // -r %s
			$this->mem_limit, // -m %d
			$this->mem_limit, // -k %d
			$this->file_limit, // -a %d
			// -f
			$filepath, // %s
			$this->time_limit, // -t %s 
			// -vvv -M -
			$this->command // -- %s
		);
		$cmd .= " >.sout 2>.serr";
//		echo "Executing sandbox...\n";
//		echo ": CMD: {$cmd}\n";
		
		shell_exec($cmd);

		//$exe = new Executor($cmd);
		//$exe->execute();
		$this->meta_content = file_get_contents('.sout');
		$this->out_content = file_get_contents('.serr');
		//$exe->join();
//		echo "Sandbox finished.\n";
		$this->parse_sandbox_meta();
	}
	
	public function parse_sandbox_meta() {
		$meta = trim($this->meta_content);
		$meta = explode("\n", $meta);
		
		$comp = array('time' => 1, 'mem' => 1);
		
		foreach ($meta as $line) {
			$line = trim($line);
			$line = explode(':', $line);
			if (count($line) > 1) {
				$title = strtolower(trim($line[0]));
				$value = trim($line[1]);
				
				$this->meta[$title] = $value;
				
				switch($title) {
					case 'time': $this->time = $value; break;
					case 'time-wall': $this->walltime = $value; break;
					case 'mem': $this->mem = $value; break;
				}
				
				if (isset($comp[$title]))
					unset($comp[$title]);
			}
		}
		
		if (count($comp) > 0) { 
			$this->status = 1;
		} else $this->status = 0;
	}
	
	public function get_sandbox_metadata() {
		return $this->meta_content;
	}
	
	public function get_sandbox_output() {
		return $this->out_content;
	}
	
	public function setMemoryLimit($kb) {
		$this->mem_limit = $kb;
	}
	
	public function setTimeLimit($s) {
		$this->time_limit = $s;
	}
	
	// 1 = normal : RECCOMMEND
	// 2 = with normal path
	// 3 = all
	// 9 = no restrict
	public function setFileLimit($level) {
		$this->file_limit = $level;
	}
	
	// 1 and 2; 1 is reccommend as 2 is too strict
	public function setSysCall($level) {
		$this->syscall_limit = $level;
	}
	
	public function addAllowPath($path) {
		$this->allow_file_path[] = $path;
	}
	
	public function redirectInput($file) {
		$this->stdin = $file;
	}
	
	public function redirectOutput($file) {
		$this->stdout = $file;
	}
	
	public function redirectError($file) {
		$this->stderr = $file;
	}
}
